
local player = {}
setmetatable(player, player)
---@class ac.player
ac.player = player

function player:__tostring()
    return ('玩家%02d|%s'):format(self.id, self.name)
end

--结构
--获取一个在线玩家
function ac.online_player()
    for a=0,11 do
        local p = ac.player[a]
        if p:is_player() then
            return p
        end
    end
end

function ac.each_player(func)
    for a=0,11 do
        local p = ac.player[a]
        if p:is_player() then
            func(p)
        end
    end
end

function ac.each_hero(func)
    local list = {}
    for i = 1, 12 do
        local player = ac.player(i)
        local hero = player.hero
        if hero and player:is_player() then
            func(hero)
        end
    end
end

local mt = {}
player.__index = mt

--- 派发全局事件(有返回值)
--- @param name string
--- @param ... any
--- @return function
function mt:dispatch(name, ...)
	local ok, res = ac.dispatch(self, name, ...)
	if ok ~= nil then 
		return ok, res 
	end 
    return ac.dispatch(ac.game,name,...)
end

--- 派发全局事件
--- @param name string
--- @param ... any
--- @return function
function mt:notify(name, ...)
	ac.notify(self, name, ...)
    ac.notify(ac.game,name,...)
end

--- 注册全局事件
--- @param name string
--- @return function
function mt:event(name)
	return ac.register(self, name)
end

--是在线玩家
function mt:is_player()
    return self.is_only
end

-- 设置自定义值
function mt:set_data(key,value)
    self.user_data = self.user_data or {}
    self.user_data[key] = value 
end

-- 获取自定义值
function mt:get_data(key,default)
    return self.user_data and self.user_data[key] or default
end

--地图等级
function mt:get_level()
    return self.map_level
end

--获取云存档
function mt:get(mkey)
    return self.ms_data[mkey]
end

--设置云存档
function mt:set(mkey, mvalue)
    self.ms_data[mkey] = mvalue
end



--保存云存档
function mt:save_msdata()
    -- 读取玩家脚本存档数据
    local start_t = os.clock()
    local text = json.encode(self.ms_data)
    local id = MsSaveScriptArchive(self.id, text, string.len(text))
    if id~=0 and id~=1 then
        local result = ('【云存档】保存结果：%s'):format(ERROE_STR[id])
        self:sendWar3('错误提示',result,text)
    end
end

--读取普通存档
function mt:getCommonArchive(key)
    return MsGetCommonArchive(self.id,key)
end

--获取只读存档
function mt:getGetReadArchive(key)
    return MsGetReadArchive(self.id,key)
end

--修改只读存档
function mt:getSetReadArchive(key)
    local id = MsSetReadArchive(self.id,key)
    if id~=0 then
        LogInfo("修改只读存档错误：[%s]%s", id,ERROE_STR[id])
    end
end


--拥有道具
function mt:has_item(key)
    return MsGetPlayerItem(self.id,key)
end

--进入游戏

function mt:loaded()
    if self.is_only then
        return
    end
    self.is_only = true

    -- 读取玩家脚本存档数据
    local hvalue = MsGetScriptArchive(self.id)
    if hvalue ~= nil and hvalue ~= '' then
        self.ms_data = json.decode(hvalue)
    end
    self:notify('玩家-初始化数据',self)
    
    self:notify('玩家-进入游戏',self)
    self:save_msdata()

end

-- 玩家离开游戏
function mt:exit_game(reason)
    local game_end_t = os.date("%Y-%m-%d %H:%M:%S")
    self.is_only = false
    -- 保存玩家最后一次退出时间
    self:set('退出时间', game_end_t)
    -- 游戏结束前，需要调用保存脚本存档
    self:notify('玩家-结束游戏',player)
    self:save_msdata()
end



--- 初始化
function player.init()
    for id=0,15 do
        local object = setmetatable({},player)
        --玩家ID
        object.id = id
        
        --是否在线
        object.is_only = false

        -- 玩家名字
        object.name = MsGetPlayerName(id)

        -- 地图等级
        object.map_level = math.max(MsGetPlayerMapLevel(id),1)

        -- 地图经验
        object.map_exp = MsGetPlayerMapExp(id)

        -- 地图游玩时间
        object.game_time = MsGetPlayedTime(id)

        -- 地图游玩次数
        object.game_count = MsGetPlayedCount(id)

        -- 云存档数据
        object.ms_data = {}

        player[id] = object

        
    end
end

ac.game:event '游戏-房间加载完毕'(function()
    player.init()
end)

ac.game:event '游戏-玩家初始化完毕'(function()
    --每隔1分钟自动保存下
    Timer.NewTicker(60,function()
        ac.each_player(function(player)
            player:save_msdata()
        end)
    end)

    --记录新一天/一周/一月
    local time = os.time() - 4*60*60
    local t1 = getTimeToTomorrow(time)
    local t2 = getTimeToNextMonday(time)
    local t3 = getTimeToNextMonth(time)
    
    ac.each_player(function(player)
        local s1 = player:get('最近登录1') or 0
        local s2 = player:get('最近登录1') or 0
        local s3 = player:get('最近登录1') or 0
        player:set('最近登录1',time + t1)
        player:set('最近登录2',time + t2)
        player:set('最近登录3',time + t3)
        if time>s1 then
            player:notify('玩家-新的一天',player)
        end
        if time>s2 then
            player:notify('玩家-新的一周',player)
        end
        if time>s3 then
            player:notify('玩家-新的一月',player)
        end
    end)
    Timer.After(t1,function()
        ac.each_player(function(player)
            local time = os.time() - 4*60*60
            local t1 = time + getTimeToTomorrow(time) + 1
            player:set('最近登录1',t1)
            player:notify('玩家-新的一天',player,t1)
        end)
    end)
    Timer.After(t2,function()
        ac.each_player(function(player)
            local time = os.time() - 4*60*60
            local t1 = time + getTimeToNextMonday(time) + 1
            player:set('最近登录2',t1)
            player:notify('玩家-新的一天',player,t1)
        end)
    end)
    Timer.After(t3,function()
        ac.each_player(function(player)
            local time = os.time() - 4*60*60
            local t1 = time + getTimeToNextMonth(time) + 1
            player:set('最近登录3',t1)
            player:notify('玩家-新的一月',player,t1)
        end)
    end)
end)


return player
